importScripts("libacodec.js");
var dAudioCallback = null
var eAudioCallback = null
var isInited = false;
var chunkSize = 65536; //64K
var videoHeaderSize =  65536;//64k
var nowVideoheaderSize = 0;

var LOG_LEVEL_JS = 0;
var LOG_LEVEL_WASM = 1;
var LOG_LEVEL_FFMPEG = 2;
var DECODER_G711A = 0;
var DECODER_AAC = 1;
var decoder_type = DECODER_G711A;
var pts = 0;


var audioSampleRate = 8000;
var audioChannelCount = 1;

var isWebCodecInited = false;
var isDAudioInited = false;
var isEAudioInited = false;

var dAudioCacheBuffer = null;
var eAudioCacheBuffer = null;

var eDefaultAudioFrameSize =  1024;
var dDefaultAudioFrameSize =  1024;

const REQUEST_CODEC_NEW          = 0x6000

const REQUEST_CODEC_READY        = 0x6001;
const REQUEST_CODEC_D_DATA       = 0x6002;
const REQUEST_CODEC_E_DATA       = 0x6003;
const REQUEST_CODEC_RELEASE      = 0x6004;
const REQUEST_CODEC_FLUSH        = 0x6005;
const REQUEST_E_CODEC_NEW        = 0x6006;

const RESPONSE_CODEC_NEW          = 0x6100;
const RESPONSE_CODEC_READY        = 0x6101;
const RESPONSE_CODEC_D_DATA       = 0x6102;
const RESPONSE_CODEC_E_DATA       = 0x6103;
const RESPONSE_CODEC_RELEASE      = 0x6104;
const RESPONSE_CODEC_FLUSH        = 0x6105;
const RESPONSE_E_CODEC_NEW        = 0x6106;

const kEndOfStream = -9999;


var initAudioDecoder = function(decoder_type,audioSampleRate,audioChannelCount){
    if(isDAudioInited) return ;
    dAudioCallback = Module.addFunction(function (buff, size, timestamp) {
        if(size == 0)
        var index = 1;
        var outArray = Module.HEAPU8.subarray(buff, buff + size);
        var data = new Uint8Array(outArray);
        var objData = {
            type:RESPONSE_CODEC_D_DATA,
            isAudio: true,
            data:data,
            pts:timestamp,
            index:index
        };
        self.postMessage(objData,[objData.data.buffer]);
        console.info("get decoded audio,data_size=",data.byteLength);
    }, 'viii');
    console.info("initAudioDecoder type",decoder_type);
    var ret = Module._openAudioDecoder(decoder_type,audioSampleRate,audioChannelCount,dAudioCallback)
    if(ret == 0) {
        dAudioCacheBuffer = Module._malloc(dDefaultAudioFrameSize);
        isDAudioInited = true;
        console.log("openAudioDecoder success");
    } else {
        isDAudioInited = false;
        console.error("openAudioDecoder failed with error", ret);
    }
    return isDAudioInited;
}

var initAudioEncoder = function(decoder_type,audioSampleRate,audioChannelCount){
    if(isEAudioInited) return ;
    eAudioCallback = Module.addFunction(function (buff, size, timestamp) {
        var index = 1;
        var outArray = Module.HEAPU8.subarray(buff, buff + size);
        var data = new Uint8Array(outArray);
        var objData = {
            type:RESPONSE_CODEC_E_DATA,
            isAudio: true,
            data:data,
            pts:timestamp,
            index:index
        };
        self.postMessage(objData,[objData.data.buffer]);
        //console.info("get decoded audio,data_size=",data.byteLength);
    }, 'viii');
    console.info("initAudioEncoder type",decoder_type);
    var ret = Module._openAudioEncoder(decoder_type,audioSampleRate,audioChannelCount,eAudioCallback)
    if(ret == 0) {
        eAudioCacheBuffer = Module._malloc(eDefaultAudioFrameSize);
        isEAudioInited = true;
        console.log("openAudioEncoder success");
    } else {
        isEAudioInited = false;
        console.error("openAudioEncoder failed with error", ret);
    }

    return isEAudioInited;
}


var initWebCodec = function(){
    if(isWebCodecInited) return ;
    var debug = 1;
    var ret =  Module._initWebAudio(debug);
    if(ret == 0) {
        isWebCodecInited = true;
        console.log("isWebCodecInited success");
    } else {
        isWebCodecInited = false;
        console.error("isWebCodecInited failed with error", ret);
    }
    return isWebCodecInited;
}



var release = function(){
    if(eAudioCacheBuffer) Module._free(eAudioCacheBuffer);
    if(dAudioCacheBuffer) Module._free(dAudioCacheBuffer);
    if(isEAudioInited) Module._closeAudioEncoder();
    if(isDAudioInited) Module._closeAudioDecoder();
    eAudioCacheBuffer = null;
    dAudioCacheBuffer = null;
    isEAudioInited = false;
    isDAudioInited = false;
    self.postMessage({
        type:RESPONSE_CODEC_RELEASE
    })
    console.info("release codec  in worker")
}

var flushCodec = function(){
    Module._flushAudioEncoder();
    Module._flushAudioDecoder();
    self.postMessage({
        type:RESPONSE_CODEC_FLUSH
    })
}

self.onmessage = function(event) { // event handler for messages from the main thread
    // console.info("onMessage",event)
    var data = event.data
    switch(data.type){
        case REQUEST_CODEC_NEW:
           var ret = initWebCodec();
             /**
             * {videoType:1}
             */
            /***
             * {audioType:1,sampleRate:8000,channelCount: 1}
             */
            if(ret)ret =  initAudioDecoder(data.audioType,data.sampleRate,data.channelCount);
            self.postMessage({
                type:RESPONSE_CODEC_NEW,
                ret : ret == 0
            });
            break;
        case REQUEST_E_CODEC_NEW:
            var ret =  initAudioEncoder(data.audioType,data.sampleRate,data.channelCount);
            self.postMessage({
                type:RESPONSE_E_CODEC_NEW,
                ret : ret == 0
            });
            break;
        case REQUEST_CODEC_D_DATA:
            var pts = 0;
            var ret = 0;
            var data = data.data
            var typedArray = new Uint8Array(data);
            var size = typedArray.length

            if(size > dDefaultAudioFrameSize){
                dDefaultAudioFrameSize = size;
                Module._free(dAudioCacheBuffer);
                dAudioCacheBuffer = Module._malloc(dDefaultAudioFrameSize);
            }
            Module.HEAPU8.set(typedArray, dAudioCacheBuffer);
            ret = Module._decodeAudio(dAudioCacheBuffer, size, pts,1);
            console.info("decodeAudio ",size);
            break;
        case REQUEST_CODEC_E_DATA:
            /**
             *  {data:data,isAudio:isAudio,pts:pts,index:index}
             */
            var pts = 0;
            var ret = 0;
            var data = data.data
            var typedArray = new Uint8Array(data);
            var size = typedArray.length

           if(size > eDefaultAudioFrameSize){
               eDefaultAudioFrameSize = size;
               Module._free(eAudioCacheBuffer);
               eAudioCacheBuffer = Module._malloc(eDefaultAudioFrameSize);
           }
           Module.HEAPU8.set(typedArray, eAudioCacheBuffer);
           ret = Module._encodeAudio(eAudioCacheBuffer, size, pts,1);
           console.info("_encodeAudio",size);
           break;
        case REQUEST_CODEC_RELEASE:
            release();
            break;
        default:
            console.info("this message type is not implemented, type= %d",data.type,REQUEST_CODEC_E_DATA);
            break;
    }
};

self.Module.onRuntimeInitialized = function() {
   console.log("libacodec.wasm has loaded");
   self.postMessage({
    type:RESPONSE_CODEC_READY
   });
}
